﻿using CsvHelper;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using 可视化工具.View.Csv文件;
using Newtonsoft.Json;
using System.Windows.Documents;
using System.Security.RightsManagement;
using System.Diagnostics;
using System.Dynamic;
using System.Text.RegularExpressions;
using Newtonsoft.Json.Linq;
using System.Windows.Input;
using System.Xml.Linq;
using HalconDotNet;
using Sunny.UI;

namespace 可视化工具.Controller.Csv文件交互
{
    public class CsvController
    {
        ///// <summary>
        ///// CSV 文件的路径
        ///// </summary>
        public string csvFilePath;
        public object _wrLock;

        /// <summary>
        /// 用来存储 CSV 中的所有数据。每个 List<string> 表示一行数据，顺序与 columnNames 对应。
        /// </summary>
        public ConcurrentQueue<List<string>> records = new ConcurrentQueue<List<string>>();

        /// <summary>
        /// 信号量用于限制同时写入文件的线程数，避免高并发时对文件的过度访问
        /// </summary>
        private readonly SemaphoreSlim _writeSemaphore = new SemaphoreSlim(1, 1);

        /// <summary>
        /// 是否已更新列头的标记
        /// </summary>
        public bool _columnsUpdated;

        /// <summary>
        /// 前端窗体的对象
        /// </summary>
        public CsvMainForm csvMainForm;

        ///// <summary>
        ///// 当前的 CancellationTokenSource 对象，用于控制取消操作
        ///// </summary>
        private CancellationTokenSource _cancellationTokenSource;

        public CsvController() { }

        public CsvController(CsvMainForm csvMainForm)
        {
            this.csvMainForm = csvMainForm;
            _columnsUpdated = false;  // 初始状态下列头未更新
            _cancellationTokenSource = new CancellationTokenSource(); // 初始化 CancellationTokenSource
        }
        /// <summary>
        /// tab页更名方法
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public bool TabPageNameChanged(string name)
        {
            try
            {
                foreach (TabPage item in csvMainForm.uiTabControlMenu1.TabPages)
                {
                    if (item.Name == name)
                    {
                        return false;
                    }
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
        public  bool IsFileLocked(string filePath)
        {
            try
            {
                
                // 尝试以独占模式打开文件
                using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
                {
                    // 如果文件成功打开，表示文件没有被占用
                    return false;
                }
            }
            catch (System.IO.FileNotFoundException ex)
            {
                return false;
            }
            catch (IOException)
            {
                // 如果捕获到IOException，说明文件正被其他进程或线程占用
                return true;
            }
        }
        /// <summary>
        /// 向 CSV 文件中添加一行数据
        /// </summary>
        /// <param name="record">每一行的数据，List<string> 的集合，顺序与 columnNames 保持一致</param>
        public void AddData(List<string> record)
        {
            try
            {
                //if (csvMainForm.hwindowFlowNodeUrseControl.runPaper)
                //{
                records.Enqueue(record);
                // 将数据添加到线程安全的队列中
                //}
            }
            catch
            {

            }
        }
        /// <summary>
        /// 每秒钟写入数据到 CSV 文件
        /// </summary>
        public async Task WriteToCsvAsync(int i = 0)
        {
            try
            {
                //获取当前时间
               // string formattedTime = DateTime.Now.ToString("yyyy_MM_dd_HH_mm");
                string formattedTime = DateTime.Now.ToString("yyyy_MM_dd");
                string fullPath = Path.Combine(csvMainForm.FullPath + "\\csv文件", $"{csvMainForm.name + "_" + formattedTime}.csv");
                if (fullPath != csvFilePath)
                {
                    //更换文件
                    csvFilePath = fullPath;
                    //更换label显示的文件
                    csvMainForm.Invoke(new Action(() => {
                        csvMainForm.uiTextBox1.Text = csvMainForm.name + "_" + formattedTime;
                    }));
                }

                if (!IsFileLocked(csvFilePath))
                {
                    //临时存储要写入的记录
                    var recordsToWrite = new List<List<string>>();
                    // 从队列中获取并清除数据
                    while (records.TryDequeue(out var record))
                    {
                        recordsToWrite.Add(record);
                    }
                    // 如果有数据要写入，调用写入 CSV 的方法
                    if (recordsToWrite.Any())
                    {
                        await WriteRecordsAsync(recordsToWrite);
                    }

                    if (i != 0)
                    {
                        ClearRow(i);
                    }
                }
            }
            catch
            {

            }
        }
        /// <summary>
        /// 将记录写入 CSV 文件
        /// </summary>
        /// <param name="records">待写入的记录集合，每一项是 CSV 文件的一行</param>
        private async Task WriteRecordsAsync(List<List<string>> records)
        {
            await _writeSemaphore.WaitAsync();  // 获取写入权限
            try
            {
                if (!File.Exists(csvFilePath))
                {
                    using (File.Create(csvFilePath)) { }
                }
                var headerWritten = File.Exists(csvFilePath) && new FileInfo(csvFilePath).Length > 0;

                using (var writer = new StreamWriter(csvFilePath, append: true, new UTF8Encoding(true)))
                using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
                {
                    // 如果文件为空或尚未写入列名，则写入列名
                    if (!headerWritten)
                    {
                        var dict = new Dictionary<string, object>();
                       List<string> headList= GetFullColumns().Split(',').ToList();
                        for (int i = 0; i < headList.Count; i++)
                        {
                            dict[headList[i]+i] = headList[i];
                        }
                        // 写入列头
                        csv.WriteRecord(dict);
                        csv.NextRecord();
                    }

                    //获取所有的列
                    List<string> fullCollumns = GetFullColumns(0);
                    foreach (List<string> record in records)
                    {
                        var dict = new Dictionary<string, object>();

                        // 遍历 cailpeVlues 字典
                        for (int i = 0; i < fullCollumns.Count; i++)
                        {
                            if (!fullCollumns[i].Contains("_@#"))
                            {
                                dict[fullCollumns[i]] = record[i];
                            }
                        }
                        // 写入该行的记录
                        csv.WriteRecord(dict);
                        csv.NextRecord();
                    }
                    records.Clear();
                    fullCollumns.Clear();
                    records = null;
                    fullCollumns = null;
                }
            }
            catch (Exception ex)
            {

            }
            finally
            {
                _writeSemaphore.Release();  // 释放写入权限
            }
        }
        /// <summary>
        /// 清理多余行并补充缺失行
        /// </summary>
        /// <param name="i">目标总行数</param>
        public async void ClearRow(int i)
        {
            try
            {
                var lines = await ReadLinesAsync();
                string lastIndex = lines[lines.Count - 1].Split(',')[0];

                // 获取当前行数
                int currentRowCount = 0;
                if(!int.TryParse(lastIndex, out currentRowCount))
                {
                    return;
                }
                // 计算需要补充的行数
                int missingRowCount = i - currentRowCount;

                if (missingRowCount <= 0)
                {
                    // 如果没有缺失行，直接返回
                    return;
                }

                // 追加缺失的行
                using (var writer = new StreamWriter(csvFilePath, append: true, new UTF8Encoding(true)))
                using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
                {
                    for (int j = 0; j < missingRowCount; j++)
                    {
                        // 构造一行数据
                        var dict = new Dictionary<string, object>
                        {
                            ["序号"] = currentRowCount + j + 1 + "_执行中断"
                        };

                        // 写入该行记录
                        csv.WriteRecord(dict);
                        csv.NextRecord();
                    }
                }
                lines.Clear();
            }
            catch (Exception ex)
            {
                // 记录异常以便排查问题
            }
        }
        /// <summary>
        /// 向 CSV 文件添加多个新列（模板匹配，精准测量模块）
        /// </summary>
        /// <param name="newColumnNames">新列名集合</param>
        public async void AddNewColumnAsync(List<string> newColumnNames, string oldCailperName = null)
        {
            try
            {
                var lines = await ReadLinesAsync();

                // 检查文件是否为空，或者没有列头
                if (lines.Count == 0 || string.IsNullOrWhiteSpace(lines[0]))
                {
                    // 如果没有数据或没有列头，则初始化列头
                    lines.Add(string.Join(",", GetFullColumns()));  // 将新的列头写入第一行
                }
                else
                {
                    // 获取文件中的第一行，即列名行
                    List<string> header = lines[0].Split(',').ToList();
                    if (newColumnNames.Count == 1)
                    {
                        if (header.Count == 1)
                        {
                            header.Add(newColumnNames[0]);
                        }
                        else
                        {
                            header[1] = newColumnNames[0];
                        }

                        // 更新第一行的列名
                        lines[0] = string.Join(",", header);
                    }
                    else
                    {
                        //表示精准测量模块
                        foreach (string newColumnName in newColumnNames)
                        {

                            // 添加新的列头到原有列头后面
                            if (!header.Contains(newColumnName))
                            {
                                header.Add(newColumnName);  // 如果新列名不重复，则添加新列
                            }
                        }
                        // 更新第一行的列名
                        lines[0] = string.Join(",", header);
                    }
                }
                // 将修改后的所有行写回文件
                WriteLinesAsync(lines);
            }
            catch
            {

            }
            finally
            {
                newColumnNames.Clear();
            }
        }
        /// <summary>
        /// 读取 CSV 文件的所有行
        /// </summary>
        private async Task<List<string>> ReadLinesAsync()
        {
            try
            {
                if (!File.Exists(csvFilePath))
                {
                    File.Create(csvFilePath).Dispose(); // 使用 Dispose 立即释放资源

                    return new List<string> { GetFullColumns() };
                }
                using (var reader = new StreamReader(csvFilePath, new UTF8Encoding(true)))
                {
                    var lines = new List<string>();
                    while (!reader.EndOfStream)
                    {
                        if (_cancellationTokenSource.Token.IsCancellationRequested)
                            break;  // 如果取消请求，则退出

                        lines.Add(reader.ReadLine());  // 读取每一行
                    }
                    if (lines.Count == 0)
                    {
                        return new List<string> { GetFullColumns() };
                    }
                    else
                    {
                        return lines;
                    }

                }
            }
            catch (Exception ex)
            {
                //MessageBox.Show( ex.Message,"无法访问csv文件");
                //File.Create(csvFilePath).Dispose(); // 使用 Dispose 立即释放资源
                return new List<string> { GetFullColumns() };
            }

        }
        /// <summary>
        /// 将所有行写入csv文件
        /// </summary>
        /// <param name="lines"></param>
        private void WriteLinesAsync(List<string> lines)
        {
            try
            {
                // 使用 UTF-8 编码写入文件，确保兼容性
                using (var writer = new StreamWriter(csvFilePath, false, new UTF8Encoding(true)))
                {
                    foreach (var line in lines)
                    {
                        if (_cancellationTokenSource.Token.IsCancellationRequested)
                            break;  // 如果取消请求，则退出

                        writer.WriteLine(line);  // 写入每一行
                    }
                }
            }
            catch (Exception ex)
            { // MessageBox.Show( ex.Message,"无法访问csv文件");
            }
            finally
            {
                lines.Clear();
            }
        }
        /// <summary>
        /// 序列化
        /// </summary>
        /// <param name="config"></param>
        /// <param name="filePath"></param>
        public void SerializeToIni(CsvConfig config, string filePath)
        {
            try
            {
                var json = JsonConvert.SerializeObject(config, Formatting.Indented); // 格式化输出
                File.WriteAllText(filePath, json); // 写入文件
            }
            catch (Exception ex)
            {
                // MessageBox.Show($"SerializeToIni failed: {ex.Message}");
            }
        }
        /// <summary>
        /// 反序列化
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public CsvConfig DeserializeFromIni(string filePath)
        {
            try
            {
                var json = File.ReadAllText(filePath); // 读取整个文件内容
                return JsonConvert.DeserializeObject<CsvConfig>(json); // 使用 JSON.NET 反序列化
            }
            catch (Exception ex)
            {
                //MessageBox.Show($"DeserializeFromIni failed: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 根清理多余的列
        /// </summary>
        /// <param name="filePath">目标文件路径</param>
        public async void ReFlushColumns()
        {
            try
            {
                // 读取文件中的所有行
                var lines = await ReadLinesAsync();
                lines[0] = GetFullColumns();
                // 将修改后的所有行写回文件
                WriteLinesAsync(lines);
            }
            catch (Exception ex)
            {
                // MessageBox.Show($"文件访问失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 删除多列
        /// </summary>
        /// <param name="beginIndex">起始列（包括起始列）</param>
        /// <param name="count">删除的列的个数</param>
        public async Task RemoveColumnsAsync(string nameHeadColumn)
        {
            try
            {
                // 读取所有行
                var lines = await ReadLinesAsync();

                // 如果文件中没有数据，直接返回
                if (lines.Count == 0)
                {
                    // 文件为空，无需处理
                    return;
                }

                // 获取文件中的第一行，即列名行
                List<string> header = lines[0].Split(',').ToList();
                int c = header.Count;
                // 查找所有包含指定关键字的列的索引
                var columnsToRemove = new List<int>();
                for (int i = 0; i < header.Count; i++)
                {
                    if (header[i].Contains(nameHeadColumn))
                    {
                        columnsToRemove.Add(i);
                    }
                }

                // 如果没有找到匹配的列，直接返回
                if (columnsToRemove.Count == 0)
                {
                    return;
                }

                // 删除列头中指定的列
                for (int i = columnsToRemove.Count - 1; i >= 0; i--)  // 从后往前删除，避免索引错位
                {
                    header.RemoveAt(columnsToRemove[i]);
                }
                lines[0] = string.Join(",", header);  // 更新第一行的列名

                // 删除每一行中的指定列
                for (int i = 1; i < lines.Count; i++) // 从第二行开始
                {
                    // 将每行的数据转换为列表
                    var row = lines[i].Split(',').ToList();

                    // 检查并补充缺失的列，确保与列名数目一致
                    while (row.Count < c)
                    {
                        row.Add(string.Empty);  // 添加空字符串以补齐
                    }
                    // 如果行中列数大于列名数目，多余的列可能是异常数据，可以裁剪到列名数目
                    if (row.Count > c)
                    {
                        row = row.Take(c).ToList();
                    }

                    // 删除指定索引的列（从后往前删除，避免索引错位）
                    for (int j = columnsToRemove.Count - 1; j >= 0; j--)
                    {
                        if (columnsToRemove[j] < row.Count)
                        {
                            row.RemoveAt(columnsToRemove[j]);
                        }
                    }

                    // 更新每一行的数据
                    lines[i] = string.Join(",", row);
                }

                // 写回文件
                WriteLinesAsync(lines);
            }
            catch (Exception ex)
            {
                // 记录异常或抛出
                // Console.WriteLine($"发生异常: {ex.Message}");
            }
        }

        /// <summary>
        /// 删除单列
        /// </summary>
        public async void RemoveOneColumn(string columnName)
        {
            try
            {
                // 读取所有行
                var lines = await ReadLinesAsync();
                // 如果文件中没有数据，直接返回
                if (lines.Count == 0)
                {
                    //MessageBox.Show("文件为空，无法删除列");
                    return;
                }
                // 获取文件中的第一行，即列名行
                List<string> header = lines[0].Split(',').ToList();
                int c = header.Count;
                int index = header.IndexOf(columnName);
                if (index == -1)
                {
                    index = GetFullColumns().Split(',').ToList().IndexOf(columnName);
                    if (index != -1)
                    {
                        header = GetFullColumns().Split(',').ToList();
                    }
                }
                if (index != -1)
                {

                    //删除指定的列
                    header.RemoveAt(index);
                    lines[0] = string.Join(",", header);    // 更新第一行的列名
                                                            // 删除每一行中的指定列
                    for (int i = 1; i < lines.Count; i++)  // 从第二行开始
                    {
                        // 将每行的数据转换为列表
                        var row = lines[i].Split(',').ToList();
                        // 检查并补充缺失的列，确保与列名数目一致
                        while (row.Count < c)
                        {
                            row.Add(string.Empty);  // 添加空字符串以补齐
                        }
                        // 如果行中列数大于列名数目，多余的列可能是异常数据，可以裁剪到列名数目
                        if (row.Count > c)
                        {
                            row = row.Take(c).ToList();
                        }
                        //删除指定的列
                        row.RemoveAt(index);
                        // 更新每一行的数据
                        lines[i] = string.Join(",", row);
                    }
                    // 写回文件
                    WriteLinesAsync(lines);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(columnName);
            }

        }
        /// <summary>
        /// 添加单列
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="index">指定位置</param>
        public async void AddOneColumn(string columnName, int cindex)
        {
            try
            {
                // 读取所有行
                var lines = await ReadLinesAsync();
                // 如果文件中没有数据，直接返回
                if (lines.Count == 0)
                {
                    //MessageBox.Show("文件为空，无法删除列");
                    return;
                }
                // 获取文件中的第一行，即列名行
                List<string> header = lines[0].Split(',').ToList();
                int c = header.Count;
                int index = header.IndexOf(columnName);
                if (index == -1)
                {
                    header.Insert(cindex, columnName);
                    lines[0] = string.Join(",", header);

                    for (int i = 1; i < lines.Count; i++)  // 从第二行开始
                    {
                        // 将每行的数据转换为列表
                        var row = lines[i].Split(',').ToList();
                        // 检查并补充缺失的列，确保与列名数目一致
                        while (row.Count < c)
                        {
                            row.Add(string.Empty);  // 添加空字符串以补齐
                        }
                        // 如果行中列数大于列名数目，多余的列可能是异常数据，可以裁剪到列名数目
                        if (row.Count > c)
                        {
                            row = row.Take(c).ToList();
                        }
                        //删除指定的列
                        row.Insert(cindex, string.Empty);
                        // 更新每一行的数据
                        lines[i] = string.Join(",", row);
                    }
                    // 写回文件
                    WriteLinesAsync(lines);
                }
            }
            catch
            {

            }
        }
        /// <summary>
        /// 清空 完美
        /// </summary>
        /// <param name="count"></param>
        public void ClearCsv()
        {
            try
            {
                while (records.TryDequeue(out var record))
                {
                    record.Clear();
                }
                // 使用 UTF-8 编码写入文件，确保兼容性
                ClearCsvHelper("*_");
            }
            catch (Exception ex)
            {
                // MessageBox.Show(ex.ToString() + ":ClearCsv");
            }
        }
        /// <summary>
        /// 给序号打上(已删除)
        /// </summary>
        public async void ClearCsvHelper(string name)
        {
            var lines = await ReadLinesAsync();
            try
            {

                // 检查文件是否为空，或者没有列头
                if (lines.Count == 0 || string.IsNullOrWhiteSpace(lines[0]))
                {
                    // 如果没有数据或没有列头，则初始化列头
                    lines.Add(string.Join(",", GetFullColumns()));  // 将新的列头写入第一行
                }
                else
                {
                    for (int i = 1; i < lines.Count; i++)
                    {
                        List<string> header = lines[i].Split(',').ToList();
                        if (!header[0].Contains(name))
                        {
                            header[0] = name + "_" + header[0];
                        }
                        // 更新每一行的列名
                        lines[i] = string.Join(",", header);
                    }
                }
                // 将修改后的所有行写回文件
                WriteLinesAsync(lines);
            }
            catch
            {

            }
            finally
            {
                lines?.Clear();
            }
        }
        /// <summary>
        /// 获取所有列名/只接收无标记的列
        /// </summary>
        /// <returns></returns>
        public string GetFullColumns()
        {
            try
            {
                var strings = new List<string>() { "序号" };
                // 添加 modelName
                if (!string.IsNullOrEmpty(csvMainForm.csvConfig.modelName))
                {
                    if (!csvMainForm.csvConfig.modelName.Contains("_@#"))
                    {
                        strings.Add(csvMainForm.csvConfig.modelName);
                    }
                }
                // 添加 cailpeVlues
                csvMainForm.csvConfig.cailpeVlues?.ToList().ForEach(item =>
                {
                    item.Value.ForEach(v =>
                    {
                        if (!v.Contains("_@#"))
                        {
                            strings.Add($"{item.Key}.{v}");
                        }
                    }
                    );
                });
                GetFullColumns(0);
                // 更新第一行的列名
                return string.Join(",", new List<string> { string.Join(",", strings) });
            }
            catch
            {
                return null;
            }
        }
        /// <summary>
        /// 获取当前所有的列
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        public List<string> GetFullColumns(int count)
        {
            try
            {
                var strings = new List<string>() { "序号" };
                // 添加 modelName
                if (!string.IsNullOrEmpty(csvMainForm.csvConfig.modelName))
                {
                    strings.Add(csvMainForm.csvConfig.modelName);
                }
                // 添加 cailpeVlues
                csvMainForm.csvConfig.cailpeVlues?.ToList().ForEach(item =>
                {
                    item.Value.ForEach(v =>
                    {
                        strings.Add($"{item.Key}.{v}");
                    }
                    );
                });
                // 更新第一行的列名
                return strings;
            }
            catch
            {
                return null;
            }
        }
    }
    [Serializable]
    public class CsvConfig
    {
        [JsonIgnore]
        public CsvController controller;
        /// <summary>
        /// 模板匹配的 列名
        /// </summary>
        public string modelName = string.Empty;
        /// <summary>
        /// 其余的列string:精准测量模块  List<string>：卡尺,距离转化,角度。。。
        /// </summary>
        public Dictionary<string, List<string>> cailpeVlues = new Dictionary<string, List<string>>();

        public CsvConfig()
        {
        }
        /// <summary>
        /// 卡尺状态—是否启用
        /// </summary>
        /// <param name="key"></param>
        /// <param name="nameIndex"></param>
        /// <param name="state"></param>
        public void cailperValueState(string key, int nameIndex, bool state)
        {
            try
            {
                string columnName = string.Empty;
                //将此列重新插入集合并从csv文件中加入
                if (state)
                {
                    int cindex = 0;
                    List<string> columns = controller.GetFullColumns(0);
                    for (int i = 0; i < columns.Count; i++)
                    {
                        string iii = key + "." + cailpeVlues[key][nameIndex];
                        if (columns[i] == iii)
                        {
                            break;
                        }
                        if (!columns[i].Contains("_@#"))
                        {
                            cindex++;
                        }
                    }

                    if (cailpeVlues[key][nameIndex].Contains("_@#"))
                    {
                        cailpeVlues[key][nameIndex] = Regex.Replace(cailpeVlues[key][nameIndex], "_@#", "");
                    }
                    //访问csv文件—添加列
                    columnName = key + "." + cailpeVlues[key][nameIndex];
                    controller.AddOneColumn(columnName, cindex);
                }
                //将此列从集合中删除并从csv文件中删除
                else
                {
                    cailpeVlues[key][nameIndex] = cailpeVlues[key][nameIndex] + "_@#";
                    //访问csv文件—删除列
                    columnName = key + "." + Regex.Replace(cailpeVlues[key][nameIndex], "_@#", "");
                    controller.RemoveOneColumn(columnName);
                }
                controller.SerializeToIni(controller.csvMainForm.csvConfig, controller.csvMainForm.FullPath + "\\csv配置文件.json");
            }
            catch
            {

            }
        }
        /// <summary>
        /// 模板匹配是否启用
        /// </summary>
        /// <param name="state"></param>
        public void ModelChange(bool state)
        {
            try
            {
                if (this.modelName == string.Empty) return;
                if (state)
                {
                    //增加模板匹配
                    if (this.modelName.Contains("_@#"))
                    {
                        this.modelName = Regex.Replace(this.modelName, "_@#", "");
                        controller.AddOneColumn(this.modelName, 1);
                    }
                }
                else
                {
                    string name = this.modelName;
                    this.modelName = this.modelName + "_@#";
                    controller.RemoveOneColumn(name);
                }
                controller.SerializeToIni(controller.csvMainForm.csvConfig, controller.csvMainForm.FullPath + "\\csv配置文件.json");
                //删除模板匹配
            }
            catch
            {

            }
        }
    }
}
